/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cn.diancan.util;

import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import sun.awt.image.PNGImageDecoder;

import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

import cn.diancan.exception.OutMsgException;
/**
 * 图片压缩
 * @author Administrator
 *
 */
public class CompressImg extends  Thread{
	
 
	public CompressImg(String sourceFile, String targetFile,int outputWidth, int outputHeight, boolean proportion) {
		super();
		this.sourceFile = sourceFile;
		this.targetFile = targetFile;
		this.outputWidth = outputWidth;
		this.outputHeight = outputHeight;
		this.proportion = proportion;
	}
     @Override
	public void run() { 
    	try { 
			compressPic( sourceFile,  targetFile, outputWidth, outputHeight, proportion);
		} catch (Exception e) { 
			e.printStackTrace();
		}
	}

	private File file = null; // 文件对象 
	 private String sourceFile; // 输入图路径
	 private String targetFile; // 输出图路径
	 private String inputFileName; // 输入图文件名
	 private String outputFileName; // 输出图文件名
	 private int outputWidth = 100; // 默认输出图片宽
	 private int outputHeight = 100; // 默认输出图片高
	 private boolean proportion = true; // 是否等比缩放标记(默认为等比缩放)
	 
	 
	 public CompressImg() { // 初始化变量
		 sourceFile = ""; 
		 targetFile = ""; 
		 inputFileName = ""; 
		 outputFileName = ""; 
		 outputWidth = 100; 
		 outputHeight = 100; 
	 } 
	 public void setInputDir(String inputDir) { 
		 this.sourceFile = inputDir; 
	 } 
	 public void setOutputDir(String outputDir) { 
		 this.targetFile = outputDir; 
	 } 
	 public void setInputFileName(String inputFileName) { 
		 this.inputFileName = inputFileName;
	 } 
	 public void setOutputFileName(String outputFileName) { 
		 this.outputFileName = outputFileName; 
	 } 
	 public void setOutputWidth(int outputWidth) {
		 this.outputWidth = outputWidth; 
	 } 
	 public void setOutputHeight(int outputHeight) { 
		 this.outputHeight = outputHeight; 
	 } 
	 public void setWidthAndHeight(int width, int height) { 
		 this.outputWidth = width;
		 this.outputHeight = height; 
	 } 

	 /* 
	  * 获得图片大小 
	  * 传入参数 String path ：图片路径 
	  */ 
	 public long getPicSize(String path) { 
		 file = new File(path); 
		 return file.length(); 
	 }
	 /**
	  * 
	  * @param sourceFile  源图
	  * @param targetFile  目标
	  * @param outputWidth  宽
	  * @param outputHeight 高
	  * @param proportion  是否缩放
	  * @throws Exception
	  */
	 public static void compressPic(String sourceFile, String targetFile,Integer outputWidth,Integer outputHeight,boolean proportion) throws Exception { 
		 long start = System.currentTimeMillis(); 
		 compressPic(sourceFile,targetFile,outputWidth,outputHeight,proportion,true);
		 System.out.println(System.currentTimeMillis()-start);
	 }
	 
 
	 
	 /**
	  * 
	  * @param sourceFile  源图
	  * @param targetFile  目标
	  * @param outputWidth  宽
	  * @param outputHeight 高
	  * @param proportion  是否缩放
	  * @param coerce  是否强制大小 
	  * @throws Exception
	  */
	 public static void compressPic(String sourceFile, String targetFile,Integer outputWidth,Integer outputHeight,boolean proportion,boolean coerce) throws Exception { 
		 File file = new File(sourceFile); 
		 if (!file.exists()) {
			 throw new IOException("改文件不存在");
		 }
		 long sourceFileLength= file.length();
		// BufferedImage img = ImageIO.read(file);  
		BufferedImage img;
		try { 
			JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream(file)); //先把流转一遍
			img = decoder.decodeAsBufferedImage();
		} catch (Exception e) { 
			System.out.println("已经错误:"+e.getMessage());
			img = ImageIO.read(file); 
		} 
		 // 判断图片格式是否正确 
		 if (img.getWidth(null) == -1) {
			 throw new IOException(" 图片错误 can't read,retry!" + "<BR>");
		 } 
		 int newWidth;
		 int newHeight; 
		 // 判断是否是等比缩放 
		 if (proportion) { 
			 if(coerce){
				 newWidth= outputWidth;
				 newHeight= outputHeight ;
			 }else{
				// 为等比缩放计算输出的图片宽度及高度 
				 double rate1 =  (double)img.getWidth(null) / (double)outputWidth; 
				 double rate2 =  (double)img.getHeight(null) / (double)outputHeight ; 
				 // 根据缩放比率大的进行缩放控制 
				 Double rate = rate1 > rate2 ? rate2 : rate1; 
				 if(rate1!=1){
					 newWidth =  (int)((double)img.getWidth(null) / rate); 
					 newHeight = (int)((double)img.getHeight(null) / rate);
				 }else{
					 newWidth=img.getWidth(null) ;
					 newHeight=img.getHeight(null);
				 }
			 } 
			 // 为等比缩放计算输出的图片宽度及高度 
			/* double rate1 = ((double) img.getWidth(null)) / (double) outputWidth + 0.1; 
			 double rate2 = ((double) img.getHeight(null)) / (double) outputHeight + 0.1; 
			 // 根据缩放比率大的进行缩放控制 
			 double rate = rate1 > rate2 ? rate1 : rate2; 
			 newWidth = (int) (((double) img.getWidth(null)) / rate); 
			 newHeight = (int) (((double) img.getHeight(null)) / rate); */
		 } else { 
			 newWidth = img.getWidth(null); // 输出的图片宽度 
			 newHeight = img.getHeight(null); // 输出的图片高度 
		 } 
		 //BufferedImage.TYPE_INT_RGB
		 BufferedImage tag = null;
		 if(img.isAlphaPremultiplied()){
			 tag =new BufferedImage((int) newWidth, (int) newHeight, BufferedImage.TRANSLUCENT);
		 }else{
			 tag = new BufferedImage((int) newWidth, (int) newHeight, BufferedImage.TYPE_INT_RGB);
		 }
		 
		 
	 	//BufferedImage tag = new BufferedImage((int) newWidth, (int) newHeight, BufferedImage.TYPE_INT_RGB);  
	 	 
		//Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的  优先级比速度高 生成的图片质量比较好 但速度慢  
	 	tag.getGraphics().drawImage(img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0,null);
	 	FileOutputStream out = new FileOutputStream(targetFile+".temp"); //创建一个临时文件
	 	// JPEGImageEncoder可适用于其他图片类型的转换 
	 	JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 
	 	encoder.encode(tag); 
	 	out.close();
	 	 
	 	//保证另起线程的时候，tomcat关闭，不会损坏文件
	 	File targetF= new File(targetFile+".temp"); 
	 	//越压越大的情况还是有的
	 	if(targetF.length()>=sourceFileLength){
	 		targetF.delete();
	 		return ;
	 	}
	 	FileUtil.copyFile(targetF, new File(targetFile));
	 	targetF.delete();
	 }
	 
	 public byte[] inputStreamToThumbnailsByte(InputStream is, int width,int hight) throws IOException {
		    ByteArrayOutputStream out = new ByteArrayOutputStream();
		    try{
		     JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(is); //先把流转一遍
		     BufferedImage image = decoder.decodeAsBufferedImage();
		     //Builder<BufferedImage> bu = Thumbnails.of(image).size(width, hight); //再根据大小转换
		     ImageIO.write(image, "jpg", out);
		     //bu.toOutputStream(out); //输出得到图片流
		    }catch(Exception  e){
		      
		    }
		    out.close();
		    return  out.toByteArray() ;  
		  }
	 
	 

	 // 图片处理 
	 public void compressPic() throws Exception { 
			 //获得源文件 
			 file = new File(sourceFile + inputFileName); 
			 if (!file.exists()) {
				 throw new IOException("改文件不存在");
			 } 
			 Image img = ImageIO.read(file); 
			 // 判断图片格式是否正确 
			 if (img.getWidth(null) == -1) {
				 System.out.println(" can't read,retry!" + "<BR>"); 
				 
			 } else { 
				 int newWidth; int newHeight; 
				 // 判断是否是等比缩放 
				 if (this.proportion == true) { 
					 newWidth= outputWidth;
					 newHeight= outputHeight ;
					/* // 为等比缩放计算输出的图片宽度及高度 
					 double rate1 = ((double) img.getWidth(null)) / (double) outputWidth + 0.1; 
					 double rate2 = ((double) img.getHeight(null)) / (double) outputHeight + 0.1; 
					 // 根据缩放比率大的进行缩放控制 
					 double rate = rate1 > rate2 ? rate1 : rate2; 
					 newWidth = (int) (((double) img.getWidth(null)) / rate); 
					 newHeight = (int) (((double) img.getHeight(null)) / rate); */
				 } else { 
					 newWidth = img.getWidth(null); // 输出的图片宽度 
					 newHeight = img.getHeight(null); // 输出的图片高度 
				 } 
			 	BufferedImage tag = new BufferedImage((int) newWidth, (int) newHeight, BufferedImage.TYPE_INT_RGB); 

			 	/*
				 * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的
				 * 优先级比速度高 生成的图片质量比较好 但速度慢
				 */ 
			 	tag.getGraphics().drawImage(img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0, null);
			 	FileOutputStream out = new FileOutputStream(targetFile + outputFileName);
			 	// JPEGImageEncoder可适用于其他图片类型的转换 
			 	JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 
			 	encoder.encode(tag); 
			 	out.close(); 
			 } 
		 
	} 
	 
 	public void compressPic (String inputDir, String outputDir, String inputFileName, String outputFileName) throws Exception { 
 		// 输入图路径 
 		this.sourceFile = inputDir; 
 		// 输出图路径 
 		this.targetFile = outputDir; 
 		// 输入图文件名 
 		this.inputFileName = inputFileName; 
 		// 输出图文件名
 		this.outputFileName = outputFileName; 
 		compressPic(); 
 	} 
 	
 	public void compressPic(String inputDir, String outputDir, String inputFileName, String outputFileName, int width, int height, boolean gp) throws Exception { 
 		// 输入图路径 
 		this.sourceFile = inputDir; 
 		// 输出图路径 
 		this.targetFile = outputDir; 
 		// 输入图文件名 
 		this.inputFileName = inputFileName; 
 		// 输出图文件名 
 		this.outputFileName = outputFileName; 
 		// 设置图片长宽
 		setWidthAndHeight(width, height); 
 		// 是否是等比缩放 标记 
 		this.proportion = gp; 
 		compressPic(); 
 	}
 	
 	/**
	 * 拷贝文件
	 * @param dirOrFile
	 * @param newFile
	 */
	public static void copyFile(File dirOrFile,String newFile){
		if(!dirOrFile.exists()){
			System.out.println("找不到 该文件:"+dirOrFile);
		}
		File newFile_=new File(newFile);
		String newParent= new File(newFile).getParent();
		File newParent_ =new File(newParent);
		if(!newParent_.exists()){
			newParent_.mkdirs();
		}
		try {
			 FileInputStream input = new FileInputStream(dirOrFile); 
			 FileOutputStream output = new FileOutputStream(newFile_); 
			 byte[] b = new byte[1024 * 5]; 
			 int len; 
			 while ( (len = input.read(b)) != -1) { 
			     output.write(b, 0, len); 
			 } 
			 output.flush(); 
			 output.close(); 
			 input.close();
		} catch (FileNotFoundException e) { 
			e.printStackTrace();
		} catch (IOException e) { 
			e.printStackTrace();
		}  
	}
	
	 

 	// main测试 
 	// compressPic(大图片路径,生成小图片路径,大图片文件名,生成小图片文名,生成小图片宽度,生成小图片高度,是否等比缩放(默认为true))
 	public static void main(String[] arg) { 
 		CompressImg mypic = new CompressImg();  
 		String filename="D:/logo.png";
 		String filename2="D:/logo21.png";
 		System.out.println("输入的图片大小：" + mypic.getPicSize(filename)/1024 + "KB");  
        try {
			//mypic.compressPic(path1, path2, filename, filename2, 10, 10, false);
        	CompressImg.compressPic(filename, filename2, 50, 28, false,false);
		} catch (Exception e) {
			e.printStackTrace();
		} 
        

 	} 
}